package com.brandservice.service;


import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Binder;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Log;

import androidx.annotation.Nullable;

import com.brandservice.BrandResult;
import com.brandservice.IBrandServiceAIDL;
import com.brandservice.TaskResult;
import com.brandservice.TaskTarget;
import com.brandservice.utils.DetectorUtil;
import com.brandservice.utils.SearchUtil;
import com.brandservice.utils.SnowFlakeUtil;

import org.pytorch.Module;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import kotlin.io.ByteStreamsKt;

public class BrandAar extends Service {
    private static final String TAG = "BrandService";

    private static final SnowFlakeUtil worker = new SnowFlakeUtil(1,1,1);

   public static Module module_ori = null;
    //用于静态加载图片库的数据

    private DetectorUtil detectorUtil;

    private final IBinder binder = new LocalBinder();

    public class LocalBinder extends Binder {
        public BrandAar getService() {
            return BrandAar.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    public BrandResult getBrandResult(ParcelFileDescriptor pfd) throws RemoteException {
        Log.d(TAG, "[sendImageAndGetResult]");
        Long start = System.currentTimeMillis();
        FileDescriptor fileDescriptor = pfd.getFileDescriptor();
        FileInputStream fis = new FileInputStream(fileDescriptor);
        byte[] data = ByteStreamsKt.readBytes((InputStream)fis);
        Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

        BrandResult brandResult = new BrandResult();

        brandResult.setTraceId(worker.nextId());
        Date date = new Date();
        @SuppressLint("SimpleDateFormat") SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss");
        brandResult.setCreateTime(dateFormat.format(date));

        /** detection **/
        TaskResult detectorResult = detectorUtil.startDetection(bitmap);
        brandResult.setDetectResult(detectorResult);
        /** detection **/

        /** search **/
//            if (detectorResult.getTargets() != null && !detectorResult.getTargets().isEmpty()) {
//                bitmap = detectorResult.getTargets().get(0).getImage();
//            }
//            TaskResult searchResult = SearchUtil.startSearch(bitmaps);
//            brandResult.setSearchResult(searchResult);
//            Log.i(TAG, searchResult.getTargets().toString());
        /** search **/

        try{
            fis.close();
        }catch (IOException e){

        }
        Long end = System.currentTimeMillis();
        brandResult.setTotalCostTime((int) (end-start));
        Log.d(TAG, "[sendImageAndGetResult]: "+brandResult.toString());
        return brandResult;
    }


    public BrandResult getBrandResultWithBitmap(Bitmap bitmap) throws RemoteException {
        return getResult(bitmap);
    }

    private BrandResult getResult(Bitmap bitmap){
        Long start = System.currentTimeMillis();
        BrandResult brandResult = new BrandResult();
        brandResult.setTraceId(worker.nextId());
        Date date = new Date();
        @SuppressLint("SimpleDateFormat") SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss");
        brandResult.setCreateTime(dateFormat.format(date));

        /** detection **/
        TaskResult detectorResult = detectorUtil.startDetection(bitmap);
        brandResult.setDetectResult(detectorResult);
        /** detection **/



        /** search **/
        List<Bitmap> bitmaps = new ArrayList<>();
        if (detectorResult.getTargets() != null && !detectorResult.getTargets().isEmpty()) {
            System.out.println("检测结果不为空");
            for(TaskTarget target: detectorResult.getTargets()){
                bitmaps.add(target.getImage());
                SearchUtil.cat = target.getName();
            }
        }
        else {
            System.out.println("检测结果为空");
            bitmaps.add(bitmap);
        }

        TaskResult searchResult = SearchUtil.startSearch(bitmaps);
        brandResult.setSearchResult(searchResult);
        Log.i(TAG, searchResult.getTargets().toString());
        /** search **/


        Long end = System.currentTimeMillis();
        brandResult.setTotalCostTime((int) (end-start));
        Log.d("[BrandService]", brandResult.toString());
        return brandResult;
    }


    public String assetFilePath(Context context, String assetName) throws IOException {
        File file = new File(context.getFilesDir(), assetName);
        if (file.exists() && file.length() > 0) {
            System.out.println(file.getAbsolutePath());
            return file.getAbsolutePath();
        }

        try (@SuppressLint({"NewApi", "LocalSuppress"}) InputStream is = context.getAssets().open(assetName)) {
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                try (OutputStream os = Files.newOutputStream(file.toPath())) {
                    byte[] buffer = new byte[4 * 1024];
                    int read;
                    while ((read = is.read(buffer)) != -1) {
                        os.write(buffer, 0, read);
                    }
                    os.flush();
                }
            }
            return file.getAbsolutePath();
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        System.out.println("*************assetManagerBrandAar************");
        AssetManager assetManager = this.getAssets();
        System.out.println("*************end assetManagerBrandAar************");
        System.out.println("assetManager: "+ assetManager.toString());
        detectorUtil = new DetectorUtil(assetManager, BrandAar.this);
        SearchUtil.am = assetManager;
        System.out.println("SearchUtil.am" + SearchUtil.am);


        try {
            module_ori = Module.load(assetFilePath(this,"resnet101_test_1023_nocuda.pt"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }





}
